<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>出纳流水账自动计算</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif;
            background-color: #f4f7fa;
        }

        table {
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
            transition: box-shadow 0.3s ease;
        }

        table:hover {
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
        }

        th,
        td {
            padding: 0.75rem 1rem;
            text-align: left;
        }

        th {
            background-color: #edf2f7;
            font-weight: 600;
        }

        tr:nth-child(even) {
            background-color: #f7fafc;
        }

        button {
            transition: all 0.3s ease;
        }

        button:hover {
            transform: scale(1.05);
        }

        input[type="date"],
        input[type="text"],
        input[type="number"] {
            border: 1px solid #cbd5e0;
            padding: 0.5rem 0.75rem;
            border-radius: 0.25rem;
            transition: border-color 0.3s ease;
        }

        input[type="date"]:focus,
        input[type="text"]:focus,
        input[type="number"]:focus {
            border-color: #63b3ed;
            outline: none;
        }

        .pagination {
            display: flex;
            justify-content: center;
            margin-top: 1rem;
        }

        .pagination button {
            margin: 0 0.25rem;
        }
    </style>
</head>

<body class="p-6">
    <h1 class="text-3xl font-bold text-gray-800 mb-6">出纳流水账自动计算</h1>
    <div class="flex flex-wrap space-x-4 space-y-4 md:space-y-0 mb-4">
        <input type="date" id="start-date" placeholder="开始日期">
        <input type="date" id="end-date" placeholder="结束日期">
        <button id="filter-button" class="bg-blue-500 text-white px-4 py-2 rounded-md">筛选</button>
        <input type="text" id="search-input" placeholder="搜索摘要" class="flex-grow">
    </div>
    <div class="overflow-x-auto">
        <table class="table-auto w-full border-collapse rounded-md overflow-hidden">
            <thead>
                <tr>
                    <th class="border-b border-gray-300">日期</th>
                    <th class="border-b border-gray-300">摘要</th>
                    <th class="border-b border-gray-300">收入</th>
                    <th class="border-b border-gray-300">支出</th>
                    <th class="border-b border-gray-300">余额</th>
                    <th class="border-b border-gray-300">类型</th>
                    <th class="border-b border-gray-300">备注</th>
                </tr>
            </thead>
            <tbody id="ledger-body">
                <!-- 流水账记录将动态添加到这里 -->
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="3" class="border-t border-gray-300 font-bold text-right">总计（现金）</td>
                    <td id="total-income-cash" class="border-t border-gray-300">0.00</td>
                    <td id="total-expense-cash" class="border-t border-gray-300">0.00</td>
                    <td id="final-balance-cash" class="border-t border-gray-300">0.00</td>
                    <td></td>
                </tr>
                <tr>
                    <td colspan="3" class="border-t border-gray-300 font-bold text-right">总计（存款）</td>
                    <td id="total-income-deposit" class="border-t border-gray-300">0.00</td>
                    <td id="total-expense-deposit" class="border-t border-gray-300">0.00</td>
                    <td id="final-balance-deposit" class="border-t border-gray-300">0.00</td>
                    <td></td>
                </tr>
                <tr>
                    <td colspan="3" class="border-t border-gray-300 font-bold text-right">总计</td>
                    <td id="total-income" class="border-t border-gray-300">0.00</td>
                    <td id="total-expense" class="border-t border-gray-300">0.00</td>
                    <td id="final-balance" class="border-t border-gray-300">0.00</td>
                    <td></td>
                </tr>
            </tfoot>
        </table>
    </div>
    <div class="pagination" id="pagination"></div>
    <div class="mt-8">
        <h2 class="text-xl font-bold text-gray-800 mb-4">添加记录</h2>
        <div class="flex flex-wrap space-x-4 space-y-4 md:space-y-0">
            <input type="date" id="date-input" class="w-full md:w-auto">
            <input type="text" id="description-input" placeholder="摘要" class="w-full md:w-auto">
            <input type="number" id="income-input" placeholder="收入" class="w-full md:w-auto">
            <input type="number" id="expense-input" placeholder="支出" class="w-full md:w-auto">
            <select id="type-input" class="w-full md:w-auto">
                <option value="现金">现金</option>
                <option value="存款">存款</option>
            </select>
            <input type="text" id="remark-input" placeholder="备注" class="w-full md:w-auto">
            <button id="add-button" class="bg-blue-500 text-white px-4 py-2 rounded-md">添加</button>
        </div>
    </div>
    <div class="mt-8 flex flex-wrap space-x-4 space-y-4 md:space-y-0">
        <button id="export-json-button" class="bg-green-500 text-white px-4 py-2 rounded-md">导出记录（JSON）</button>
        <button id="export-csv-button" class="bg-orange-500 text-white px-4 py-2 rounded-md">导出记录（CSV）</button>
        <input type="file" id="import-input" class="border border-gray-300 p-2 rounded-md">
        <button id="import-button" class="bg-yellow-500 text-white px-4 py-2 rounded-md">导入记录</button>
    </div>

    <script>
        const ledgerBody = document.getElementById('ledger-body');
        const totalIncomeElement = document.getElementById('total-income');
        const totalExpenseElement = document.getElementById('total-expense');
        const finalBalanceElement = document.getElementById('final-balance');
        const totalIncomeCashElement = document.getElementById('total-income-cash');
        const totalExpenseCashElement = document.getElementById('total-expense-cash');
        const finalBalanceCashElement = document.getElementById('final-balance-cash');
        const totalIncomeDepositElement = document.getElementById('total-income-deposit');
        const totalExpenseDepositElement = document.getElementById('total-expense-deposit');
        const finalBalanceDepositElement = document.getElementById('final-balance-deposit');
        const addButton = document.getElementById('add-button');
        const dateInput = document.getElementById('date-input');
        const exportJsonButton = document.getElementById('export-json-button');
        const exportCsvButton = document.getElementById('export-csv-button');
        const importInput = document.getElementById('import-input');
        const importButton = document.getElementById('import-button');
        const searchInput = document.getElementById('search-input');
        const pagination = document.getElementById('pagination');
        const startDateInput = document.getElementById('start-date');
        const endDateInput = document.getElementById('end-date');
        const filterButton = document.getElementById('filter-button');
        const typeInput = document.getElementById('type-input');
        const remarkInput = document.getElementById('remark-input');

        let totalIncome = 0;
        let totalExpense = 0;
        let balance = 0;
        let totalIncomeCash = 0;
        let totalExpenseCash = 0;
        let balanceCash = 0;
        let totalIncomeDeposit = 0;
        let totalExpenseDeposit = 0;
        let balanceDeposit = 0;
        let currentPage = 1;
        const itemsPerPage = 10;
        let allRecords = JSON.parse(localStorage.getItem('ledgerRecords')) || [];

        // 设置日期输入框的默认值为当日日期
        const today = new Date();
        const year = today.getFullYear();
        const month = String(today.getMonth() + 1).padStart(2, '0');
        const day = String(today.getDate()).padStart(2, '0');
        const formattedDate = `${year}-${month}-${day}`;
        dateInput.value = formattedDate;

        function renderTable() {
            const startDate = startDateInput.value;
            const endDate = endDateInput.value;
            const startIndex = (currentPage - 1) * itemsPerPage;
            const endIndex = startIndex + itemsPerPage;
            const filteredRecords = allRecords.filter(record => {
                const recordDate = record.date;
                const isInDateRange = (!startDate || recordDate >= startDate) && (!endDate || recordDate <= endDate);
                const isInSearch = record.description.toLowerCase().includes(searchInput.value.toLowerCase());
                return isInDateRange && isInSearch;
            });
            const currentRecords = filteredRecords.slice(startIndex, endIndex);

            ledgerBody.innerHTML = '';
            currentRecords.forEach(record => {
                const { date, description, income, expense, balance, type, remark } = record;
                const newRow = document.createElement('tr');
                newRow.innerHTML = `
                    <td class="border-b border-gray-300">${date}</td>
                    <td class="border-b border-gray-300">${description}</td>
                    <td class="border-b border-gray-300">${income.toFixed(2)}</td>
                    <td class="border-b border-gray-300">${expense.toFixed(2)}</td>
                    <td class="border-b border-gray-300">${balance.toFixed(2)}</td>
                    <td class="border-b border-gray-300">${type}</td>
                    <td class="border-b border-gray-300">${remark}</td>
                `;
                ledgerBody.appendChild(newRow);
            });

            // 重新计算总计
            totalIncome = filteredRecords.reduce((sum, record) => sum + record.income, 0);
            totalExpense = filteredRecords.reduce((sum, record) => sum + record.expense, 0);
            balance = totalIncome - totalExpense;
            totalIncomeCash = filteredRecords.filter(record => record.type === '现金').reduce((sum, record) => sum + record.income, 0);
            totalExpenseCash = filteredRecords.filter(record => record.type === '现金').reduce((sum, record) => sum + record.expense, 0);
            balanceCash = totalIncomeCash - totalExpenseCash;
            totalIncomeDeposit = filteredRecords.filter(record => record.type === '存款').reduce((sum, record) => sum + record.income, 0);
            totalExpenseDeposit = filteredRecords.filter(record => record.type === '存款').reduce((sum, record) => sum + record.expense, 0);
            balanceDeposit = totalIncomeDeposit - totalExpenseDeposit;

            totalIncomeElement.textContent = totalIncome.toFixed(2);
            totalExpenseElement.textContent = totalExpense.toFixed(2);
            finalBalanceElement.textContent = balance.toFixed(2);
            totalIncomeCashElement.textContent = totalIncomeCash.toFixed(2);
            totalExpenseCashElement.textContent = totalExpenseCash.toFixed(2);
            finalBalanceCashElement.textContent = balanceCash.toFixed(2);
            totalIncomeDepositElement.textContent = totalIncomeDeposit.toFixed(2);
            totalExpenseDepositElement.textContent = totalExpenseDeposit.toFixed(2);
            finalBalanceDepositElement.textContent = balanceDeposit.toFixed(2);

            renderPagination(filteredRecords.length);
        }

        function renderPagination(totalRecords) {
            const totalPages = Math.ceil(totalRecords / itemsPerPage);
            pagination.innerHTML = '';

            for (let i = 1; i <= totalPages; i++) {
                const button = document.createElement('button');
                button.textContent = i;
                button.classList.add('bg-gray-200', 'text-gray-700', 'px-3', 'py-1', 'rounded-md');
                if (i === currentPage) {
                    button.classList.add('bg-blue-500', 'text-white');
                }
                button.addEventListener('click', () => {
                    currentPage = i;
                    renderTable();
                });
                pagination.appendChild(button);
            }
        }

        addButton.addEventListener('click', function () {
            const date = dateInput.value;
            const description = document.getElementById('description-input').value;
            const income = parseFloat(document.getElementById('income-input').value) || 0;
            const expense = parseFloat(document.getElementById('expense-input').value) || 0;
            const type = typeInput.value;
            const remark = remarkInput.value;

            if (type === '现金') {
                totalIncomeCash += income;
                totalExpenseCash += expense;
                balanceCash = totalIncomeCash - totalExpenseCash;
            } else if (type === '存款') {
                totalIncomeDeposit += income;
                totalExpenseDeposit += expense;
                balanceDeposit = totalIncomeDeposit - totalExpenseDeposit;
            }

            totalIncome += income;
            totalExpense += expense;
            balance = totalIncome - totalExpense;

            allRecords.push({ date, description, income, expense, balance: type === '现金' ? balanceCash : balanceDeposit, type, remark });
            localStorage.setItem('ledgerRecords', JSON.stringify(allRecords));
            renderTable();

            dateInput.value = formattedDate;
            document.getElementById('description-input').value = '';
            document.getElementById('income-input').value = '';
            document.getElementById('expense-input').value = '';
            remarkInput.value = '';
        });

        exportJsonButton.addEventListener('click', function () {
            const jsonData = JSON.stringify(allRecords);
            const blob = new Blob([jsonData], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            const fileName = `出纳日记流水账_${formattedDate}.json`;
            a.href = url;
            a.download = fileName;
            a.click();
            URL.revokeObjectURL(url);
        });

        exportCsvButton.addEventListener('click', function () {
            let csvContent = "日期,摘要,收入,支出,余额,类型,备注\n";
            allRecords.forEach(record => {
                const { date, description, income, expense, balance, type, remark } = record;
                csvContent += `${date},${description},${income.toFixed(2)},${expense.toFixed(2)},${balance.toFixed(2)},${type},${remark}\n`;
            });
            const blob = new Blob([csvContent], { type: 'text/csv' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            const fileName = `出纳日记流水账_${formattedDate}.csv`;
            a.href = url;
            a.download = fileName;
            a.click();
            URL.revokeObjectURL(url);
        });

        importButton.addEventListener('click', function () {
            const file = importInput.files[0];
            if (file) {
                // 清空现有数据
                allRecords = [];
                currentPage = 1;
                ledgerBody.innerHTML = '';
                totalIncome = 0;
                totalExpense = 0;
                balance = 0;
                totalIncomeCash = 0;
                totalExpenseCash = 0;
                balanceCash = 0;
                totalIncomeDeposit = 0;
                totalExpenseDeposit = 0;
                balanceDeposit = 0;

                const reader = new FileReader();
                reader.onload = function (e) {
                    const importedData = JSON.parse(e.target.result);
                    importedData.forEach(item => {
                        const { date, description, income, expense, type, remark } = item;
                        if (type === '现金') {
                            totalIncomeCash += income;
                            totalExpenseCash += expense;
                            balanceCash = totalIncomeCash - totalExpenseCash;
                        } else if (type === '存款') {
                            totalIncomeDeposit += income;
                            totalExpenseDeposit += expense;
                            balanceDeposit = totalIncomeDeposit - totalExpenseDeposit;
                        }

                        totalIncome += income;
                        totalExpense += expense;
                        balance = totalIncome - totalExpense;

                        allRecords.push({ date, description, income, expense, balance: type === '现金' ? balanceCash : balanceDeposit, type, remark });
                    });
                    localStorage.setItem('ledgerRecords', JSON.stringify(allRecords));
                    renderTable();

                    // 清空导入框内容
                    importInput.value = '';
                };
                reader.readAsText(file);
            }
        });

        searchInput.addEventListener('input', function () {
            currentPage = 1;
            renderTable();
        });

        filterButton.addEventListener('click', function () {
            currentPage = 1;
            renderTable();
        });

        // 页面加载时渲染表格
        renderTable();
    </script>
</body>

</html>    